ENT.Type = "brush"

local KeyValueInfo = {ScriptName = 3, model = 3, targetname = 3, target = 3, 
					  StartDisabled = 1, spawnflags = 2, origin = 3, landmark = 3, 
					  classname = 3, hammerid = 2}

local OutputInfo = {  OnStartTouch = false, OnEndTouch = false, 
					  OnStartTouchAll = false, OnEndTouchAll = false}					  
							  
local TELEPORT_SF = {	Clients = 1, 
						NPCs = 2,
						Pushables = 4, 
						PhysicsObj = 8,
						PlayerAllyNPCs = 16,
						PreserveAngles = 32 }

--[[
1 : Clients
2 : NPCs
4 : Pushables
8 : Physics Objects
16 : Only player ally NPCs
32 : Preserve angles even when a local landmark is not specified
12 : ???? (unknown Flag Only on HL2-DM)
--]]

function ENT:OnRemove()
end	

function ENT:Think()
end
	
function ENT:PassesTriggerFilters( ent )
end	

function ENT:AcceptInput( name, activator, caller, data)

	if !(name == nil) then print(tostring(name)) end
	if !(activator == nil) then print(tostring(activator)) end
	if !(caller == nil) then print(tostring(caller)) end
	
	if !(name == nil) then 
		
		if name == "Enable" then self.enabled = true end
		if name == "Disable" then self.enabled = false end
		if name == "Toggle" then self.enabled = !self.enabled end
		
	end
	data = data or " no data "
	print(tostring(self) .. " with Input : " .. tostring(name) .. " : " .. tostring(activator)  .. " : " .. tostring(caller) .. " : " .. tostring(data))
end	

function ENT:getBoundingBox( ent )

	entTable = {}
	bboxMin = ent:LocalToWorld(ent:OBBMins())
	bboxMax = ent:LocalToWorld(ent:OBBMaxs())
	
	local vecDem = Vector(math.abs(bboxMax.x - bboxMin.x), math.abs(bboxMax.y - bboxMin.y),math.abs(bboxMax.z - bboxMin.z))
	
	entTable, bboxMin, bboxMax = self:getBoundingBoxIterator(ent, entTable, bboxMin, bboxMax, ent)
	
	vecDem = Vector(math.abs(bboxMax.x - bboxMin.x), math.abs(bboxMax.y - bboxMin.y),math.abs(bboxMax.z - bboxMin.z))

	return entTable, bboxMin, bboxMax
	
end

function ENT:getBoundingBoxIterator( ent, entTable, bboxMin, bboxMax, oEnt)

	if entTable ==  nil then 
		entTable = { ent } 
	else
		table.insert(entTable, ent)
	end

	local eBBmin = ent:LocalToWorld(ent:OBBMins())
	local eBBmax = ent:LocalToWorld(ent:OBBMaxs())
	
	if eBBmin.x <= bboxMin.x then bboxMin.x = eBBmin.x end
	if eBBmin.y <= bboxMin.y then bboxMin.y = eBBmin.y end
	if eBBmin.z <= bboxMin.z then bboxMin.z = eBBmin.z end
	
	if eBBmax.x >= bboxMax.x then bboxMax.x = eBBmax.x end
	if eBBmax.y >= bboxMax.y then bboxMax.y = eBBmax.y end
	if eBBmax.z >= bboxMax.z then bboxMax.z = eBBmax.z end
	
	if constraint.HasConstraints(ent) then
		for _, cEnt in pairs(constraint.GetAllConstrainedEntities(ent)) do
			if constraint.HasConstraints(cEnt) then
				if !table.HasValue(entTable, cEnt) then
					self:getBoundingBoxIterator( cEnt, entTable, bboxMin, bboxMax, oEnt)
				end
			else
				table.insert(entTable, cEnt)
			end
			eBBmin = cEnt:LocalToWorld(cEnt:OBBMins())
			eBBmax = cEnt:LocalToWorld(cEnt:OBBMaxs())
			
			if eBBmin.x <= bboxMin.x then bboxMin.x = eBBmin.x end
			if eBBmin.y <= bboxMin.y then bboxMin.y = eBBmin.y end
			if eBBmin.z <= bboxMin.z then bboxMin.z = eBBmin.z end
			
			if eBBmax.x >= bboxMax.x then bboxMax.x = eBBmax.x end
			if eBBmax.y >= bboxMax.y then bboxMax.y = eBBmax.y end
			if eBBmax.z >= bboxMax.z then bboxMax.z = eBBmax.z end
		end
	end
		
	return entTable, bboxMin, bboxMax
	
end

function ENT:FindDestByName( name )
	
		for i, j in pairs(ents.GetAll()) do
			if j:GetName() == name then
				return j:GetPos()
			end
		end

		return Vector(0,0,0)
end

function ENT:Initialize()
        
		self:SetModel(self.model)
         
        self:SetSolid( SOLID_BBOX )
        self:SetTrigger( true )
   
        self:SetCollisionGroup( COLLISION_GROUP_WORLD )
        
		self.Destination = self:FindDestByName( self.target )
        
end
 
function ENT:KeyValue( key, value )

	--print( tostring( self ) .. " with -- Key: " .. key .. "\tValue: " .. tostring( value ) )
     
    local typ = KeyValueInfo[key]
    if ( typ ) then
        if ( typ == 1 ) then
            self[key] = tobool( value )
        elseif ( typ == 2 ) then
            self[key] = tonumber( value )
        elseif ( typ == 3 ) then
            self[key] = value
        end
    elseif ( OutputInfo[key] ) then
        self:StoreOutput( key, value )
    end
	
end

function ENT:StartTouch( ent )
	--if ent.lastTele == nil then ent.lastTele = CurTime() - 1 end
	if ValidEntity(ent) then
		local saveVel = ent:GetVelocity()
		local mEntTable, mBBoxMins, mBBoxMaxs = self:getBoundingBox(ent)
		local vecDem = Vector(self:WorldToLocal(mBBoxMaxs).x - self:WorldToLocal(mBBoxMins).x, self:WorldToLocal(mBBoxMaxs).y - self:WorldToLocal(mBBoxMins).y,self:WorldToLocal(mBBoxMaxs).z - self:WorldToLocal(mBBoxMins).z)
				
		vecLandmark = self:FindDestByName( self.landmark )

		for j, l in pairs(mEntTable) do
			TeleOffset = l:GetPos() - vecLandmark
			l:SetPos((self.Destination + TeleOffset)  + (l:GetVelocity():GetNormal() * vecDem:Length()))
			--if !l == ent then l.lastTele = CurTime() end
			local lPhys = l:GetPhysicsObject()
			if !(lPhys == nil) then
				if lPhys:IsValid() then
					l.savedVel = saveVel
				end
			end

		end
		--ent.lastTele = CurTime()
	end
end	

function ENT:EndTouch( ent )
	local ePhys = ent:GetPhysicsObject()
	if !(ePhys == nil) then
		if ePhys:IsValid() then
			if !(ent.savedVel == nil) then
				ePhys:SetVelocityInstantaneous(ent.savedVel)
			end
		end
	end
end	

scripted_ents.Register( ENT, "trigger_teleport", true)